package tsif.tcluster.netty;

import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.util.concurrent.DefaultThreadFactory;
import tsif.tcluster.TClusterContext;
import tsif.tcluster.session.TClusterSession;

/**
 * Netty集群环境<br>
 * 用netty实现集群访问
 */
public class TClusterNettyContext extends TClusterContext {
	protected TClusterNettyServer server;
	protected TClusterNettyClient client;
	protected NioEventLoopGroup eventLoopGroup; // netty线程池

	public TClusterNettyContext() {
		super();
	}

	public TClusterNettyContext(boolean useServiceClassLoader) {
		super(useServiceClassLoader);
		// Executors
	}

	/** 事件线程池(不要被其他人使用, 避免卡主) **/
	protected NioEventLoopGroup getEventLoopGroup() {
		return eventLoopGroup;
	}

	@Override
	protected TClusterSession createSession(int contextId, String host, int port) {
		// System.out.println("create session! " + contextId);
		return client.connectSession(contextId, host, port);
	}

	/** 创建集群服务器 **/
	protected TClusterNettyServer createClusterServer() {
		return new TClusterNettyServer(this);
	}

	/** 创建集群服务 **/
	protected TClusterNettyClient createClusterClient() {
		return new TClusterNettyClient(this);
	}

	@Override
	protected boolean init(int contextId, String host, final int port, String mhost, int mport) {
		// init netty
		int thread = Runtime.getRuntime().availableProcessors(); // 这个基于有多少个集群云, 如果只有几台, 实际上用不上那么多线程
		eventLoopGroup = new NioEventLoopGroup(thread, new DefaultThreadFactory("TClusterNettyContext[" + host + ":" + port + "]"));

		try {
			// create server
			server = createClusterServer();
			if (!server.startSync(port)) {
				throw new RuntimeException("server port conflict:" + port);
			}
		} catch (RuntimeException e) {
			throw e;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		try {
			// create server
			client = createClusterClient();
			if (!client.start(thread)) {
				throw new RuntimeException("client port conflict:" + port);
			}
		} catch (RuntimeException e) {
			throw e;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}

		// init server
		if (!super.init(contextId, host, port, mhost, mport)) {
			return false;
		}
		return true;
	}

	@Override
	public void stop() {
		super.stop();

		if (client != null) {
			client.stop();
			client = null;
		}

		if (server != null) {
			server.stop();
			server = null;
		}

		try {
			// shutdown
			if (eventLoopGroup != null) {
				if (!eventLoopGroup.isShutdown()) {
					// eventLoopGroup.shutdownGracefully().sync(); // 不能阻塞, 万一在自己的处理线程中执行关闭就死锁了.
					eventLoopGroup.shutdownGracefully();
					// eventLoopGroup.awaitTermination(5, TimeUnit.SECONDS); // 不等
				}
				eventLoopGroup = null;
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public TClusterNettyServer getServer() {
		return server;
	}

	public TClusterNettyClient getClient() {
		return client;
	}

}
